home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / fsio / fsioMigrate.c < prev    next >
C/C++ Source or Header  |  1990-11-06  |  14KB  |  419 lines

  1. /*
  2.  * fsioMigrate.c --
  3.  *
  4.  * Procedures to handle migrating open files between machines.  The basic
  5.  * strategy is to first do some local book-keeping on the client we are
  6.  * leaving, then ship state to the new client, then finally tell the
  7.  * I/O server about it, and finish up with local book-keeping on the
  8.  * new client.  There are three stream-type procedures used: 'migStart'
  9.  * does the initial book-keeping on the original client, 'migEnd' does
  10.  * the final book-keeping on the new client, and 'migrate' is called
  11.  * on the I/O server to shift around state associated with the client.
  12.  *
  13.  * Copyright (C) 1985, 1988, 1989 Regents of the University of California
  14.  * Permission to use, copy, modify, and distribute this
  15.  * software and its documentation for any purpose and without
  16.  * fee is hereby granted, provided that the above copyright
  17.  * notice appear in all copies.  The University of California
  18.  * makes no representations about the suitability of this
  19.  * software for any purpose.  It is provided "as is" without
  20.  * express or implied warranty.
  21.  */
  22.  
  23. #ifndef lint
  24. static char rcsid[] = "$Header: /sprite/src/kernel/fsio/RCS/fsioMigrate.c,v 9.6 90/11/06 17:37:14 rab Exp $ SPRITE (Berkeley)";
  25. #endif not lint
  26.  
  27.  
  28. #include <sprite.h>
  29. #include <fs.h>
  30. #include <fsutil.h>
  31. #include <fsio.h>
  32. #include <fsconsist.h>
  33. #include <fspdev.h>
  34. #include <fsprefix.h>
  35. #include <fsNameOps.h>
  36. #include <fsStat.h>
  37. #include <byte.h>
  38. #include <rpc.h>
  39. #include <procMigrate.h>
  40.  
  41. #include <stdio.h>
  42. #include <assert.h>
  43.  
  44. Boolean fsio_MigDebug = FALSE;
  45. #define DEBUG( format ) \
  46.     if (fsio_MigDebug) { printf format ; }
  47.  
  48.  
  49. /*
  50.  * ----------------------------------------------------------------------------
  51.  *
  52.  * Fsio_EncapStream --
  53.  *
  54.  *    Package up a stream's state for migration to another host.  This
  55.  *    copies the stream's offset, streamID, ioFileID, nameFileID, and flags.
  56.  *    This routine is side-effect free with respect to both
  57.  *    the stream and the I/O handles.  The bookkeeping is done later
  58.  *    during Fsio_DeencapStream so proper syncronization with Fs_Close
  59.  *    bookkeeping can be done.
  60.  *    It is reasonable to call Fsio_DeencapStream again on this host,
  61.  *    for example, to back out an aborted migration.
  62.  *
  63.  * Results:
  64.  *    This always returns SUCCESS.
  65.  *    
  66.  *
  67.  * Side effects:
  68.  *    None.
  69.  *
  70.  * ----------------------------------------------------------------------------
  71.  *
  72.  */
  73.  
  74. ReturnStatus
  75. Fsio_EncapStream(streamPtr, bufPtr)
  76.     Fs_Stream    *streamPtr;    /* Stream to be migrated */
  77.     Address    bufPtr;        /* Buffer to hold encapsulated stream */
  78. {
  79.     register    Fsio_MigInfo    *migInfoPtr;
  80.     register Fs_HandleHeader    *ioHandlePtr;
  81.  
  82.     /*
  83.      * Synchronize with stream duplication and closes
  84.      */
  85.     Fsutil_HandleLock(streamPtr);
  86.  
  87.     /*
  88.      * The encapsulated stream state includes the read/write offset,
  89.      * the I/O server, the useFlags of the stream, and our SpriteID so
  90.      * the target of migration and the server can do the right thing later. 
  91.      */
  92.     migInfoPtr = (Fsio_MigInfo *) bufPtr;
  93.     ioHandlePtr = streamPtr->ioHandlePtr;
  94.     migInfoPtr->streamID = streamPtr->hdr.fileID;
  95.     migInfoPtr->ioFileID = ioHandlePtr->fileID;
  96.     if (streamPtr->nameInfoPtr == (Fs_NameInfo *)NIL) {
  97.     /*
  98.      * Anonymous pipes have no name information.
  99.      */
  100.     migInfoPtr->nameID.type = -1;
  101.     } else {
  102.     migInfoPtr->nameID = streamPtr->nameInfoPtr->fileID;
  103.     migInfoPtr->rootID = streamPtr->nameInfoPtr->rootID;
  104.     }
  105.     /*
  106.      * Offset is no longer used by the I/O server -- should remove once
  107.      * new RPCs in place.
  108.      */
  109.     migInfoPtr->offset = streamPtr->offset;
  110.  
  111.     migInfoPtr->srcClientID = rpc_SpriteID;
  112.     migInfoPtr->flags = streamPtr->flags | FS_MIGRATED_FILE;
  113.  
  114.     Fsutil_HandleUnlock(streamPtr);
  115.  
  116.     return(SUCCESS);
  117. }
  118.  
  119. /*
  120.  * ----------------------------------------------------------------------------
  121.  *
  122.  * Fsio_DeencapStream --
  123.  *
  124.  *    Deencapsulate the stream that was packaged up on another machine
  125.  *    and recreate the stream on this machine.  This uses two stream-type
  126.  *    routines to complete the setup of the stream.  First, the
  127.  *    migrate routine is called to shift client references on the
  128.  *    server.  Then the migEnd routine is called to do local book-keeping.
  129.  *
  130.  * Results:
  131.  *    A return status, plus *streamPtrPtr is set to the new stream.
  132.  *
  133.  * Side effects:
  134.  *    Ensures that the stream exists on this host, along with the
  135.  *    associated I/O handle.  This calls a stream-type specific routine
  136.  *    to shuffle reference counts and detect cross-machine stream
  137.  *    sharing.  If a stream is shared by proceses on different machines
  138.  *    its flags field is marked with FS_RMT_SHARED.  This also calls
  139.  *    a stream-type specific routine to create the I/O handle when the
  140.  *    first reference to a stream migrates to this host.
  141.  *
  142.  * ----------------------------------------------------------------------------
  143.  *
  144.  */
  145.  
  146. ReturnStatus
  147. Fsio_DeencapStream(bufPtr, streamPtrPtr)
  148.     Address    bufPtr;        /* Encapsulated stream information. */
  149.     Fs_Stream    **streamPtrPtr;    /* Where to return pointer to the new stream */
  150. {
  151.     register    Fs_Stream    *streamPtr;
  152.     register    Fsio_MigInfo    *migInfoPtr;
  153.     register    Fs_NameInfo    *nameInfoPtr;
  154.     ReturnStatus        status = SUCCESS;
  155.     Boolean            foundClient;
  156.     Boolean            foundStream;
  157.     int                savedOffset;
  158.     int                size;
  159.     ClientData            data;
  160.  
  161.     migInfoPtr = (Fsio_MigInfo *) bufPtr;
  162.  
  163.     if (migInfoPtr->srcClientID == rpc_SpriteID) {
  164.     /*
  165.      * Migrating to ourselves.  Just fetch the stream.
  166.      */
  167.     *streamPtrPtr = Fsutil_HandleFetchType(Fs_Stream, &migInfoPtr->streamID);
  168.     if (*streamPtrPtr == (Fs_Stream *)NIL) {
  169.         return(FS_FILE_NOT_FOUND);
  170.     } else {
  171.         return(SUCCESS);
  172.     }
  173.     }
  174.     /*
  175.      * Create a top-level stream and note if this is a new stream.  This is
  176.      * important because extra things happen when the first reference to
  177.      * a stream migrates to this host.  FS_NEW_STREAM is used to indicate this.
  178.      * Note that the stream has (at least) one reference count and a client
  179.      * list entry that will be cleaned up by a future call to Fs_Close.
  180.      */
  181.     streamPtr = Fsio_StreamAddClient(&migInfoPtr->streamID, rpc_SpriteID,
  182.                  (Fs_HandleHeader *)NIL,
  183.                  (int) (migInfoPtr->flags & ~FS_NEW_STREAM), 
  184.                  (char *)NIL, &foundClient, &foundStream);
  185.     savedOffset = migInfoPtr->offset;
  186.     if (!foundClient) {
  187.     migInfoPtr->flags |= FS_NEW_STREAM;
  188.     streamPtr->offset = migInfoPtr->offset;
  189.     DEBUG( ("Deencap NEW stream %d, migOff %d, ",
  190.         streamPtr->hdr.fileID.minor, migInfoPtr->offset) );
  191.     } else {
  192.     migInfoPtr->flags &= ~FS_NEW_STREAM;
  193.     DEBUG( ("Deencap OLD stream %d, migOff %d, ",
  194.         streamPtr->hdr.fileID.minor,
  195.         migInfoPtr->offset, streamPtr->offset) );
  196.     }
  197.     if (streamPtr->nameInfoPtr == (Fs_NameInfo *)NIL) {
  198.     if (migInfoPtr->nameID.type == -1) {
  199.         /*
  200.          * No name info to re-create.  This happens when anonymous
  201.          * pipes get migrated.
  202.          */
  203.         streamPtr->nameInfoPtr = (Fs_NameInfo *)NIL;
  204.     } else {
  205.         /*
  206.          * Set up the nameInfo.  We sacrifice the name string as it is only
  207.          * used in error messages.  The fileID is used with get/set attr.
  208.          * If this file is the current directory then rootID is passed
  209.          * to the server to trap "..", domainType is used to index the
  210.          * name lookup operation switch, and prefixPtr is used for
  211.          * efficient handling of lookup redirections.
  212.          * Convert from remote to local file types, and vice-versa,
  213.          * as needed.
  214.          */
  215.         streamPtr->nameInfoPtr = nameInfoPtr = mnew(Fs_NameInfo);
  216.         nameInfoPtr->fileID = migInfoPtr->nameID;
  217.         nameInfoPtr->rootID = migInfoPtr->rootID;
  218.         if (nameInfoPtr->fileID.serverID != rpc_SpriteID) {
  219.         nameInfoPtr->domainType = FS_REMOTE_SPRITE_DOMAIN;
  220.         nameInfoPtr->fileID.type =
  221.             fsio_LclToRmtType[nameInfoPtr->fileID.type];
  222.         nameInfoPtr->rootID.type =
  223.             fsio_LclToRmtType[nameInfoPtr->rootID.type];
  224.         } else {
  225.         /*
  226.          * FIX HERE PROBABLY TO HANDLE PSEUDO_FILE_SYSTEMS.
  227.          */
  228.         nameInfoPtr->domainType = FS_LOCAL_DOMAIN;
  229.         nameInfoPtr->fileID.type =
  230.             fsio_RmtToLclType[nameInfoPtr->fileID.type];
  231.         nameInfoPtr->rootID.type =
  232.             fsio_RmtToLclType[nameInfoPtr->rootID.type];
  233.         }
  234.         nameInfoPtr->prefixPtr = Fsprefix_FromFileID(&migInfoPtr->rootID);
  235.         if (nameInfoPtr->prefixPtr == (struct Fsprefix *)NIL) {
  236.         printf("Fsio_DeencapStream: No prefix entry for <%d,%d,%d>\n",
  237.             migInfoPtr->rootID.serverID,
  238.             migInfoPtr->rootID.major, migInfoPtr->rootID.minor);
  239.         }
  240.     }
  241.     }
  242.     /*
  243.      * Contact the I/O server to tell it that the client moved.  The I/O
  244.      * server checks for cross-network stream sharing and sets the
  245.      * FS_RMT_SHARED flag if it is shared.  Note that we set FS_NEW_STREAM
  246.      * in the migInfoPtr->flags, and this flag often gets rammed into
  247.      * the streamPtr->flags, which we don't want because it would confuse
  248.      * Fsio_MigrateUseCounts on subsequent migrations.
  249.      */
  250.     Fsutil_HandleUnlock(streamPtr);
  251.     status = (*fsio_StreamOpTable[migInfoPtr->ioFileID.type].migrate)
  252.         (migInfoPtr, rpc_SpriteID, &streamPtr->flags,
  253.          &streamPtr->offset, &size, (Address *) &data);
  254.     streamPtr->flags &= ~FS_NEW_STREAM;
  255.  
  256.     DEBUG( (" Type %d <%d,%d> offset %d, ", migInfoPtr->ioFileID.type,
  257.         migInfoPtr->ioFileID.major, migInfoPtr->ioFileID.minor,
  258.         streamPtr->offset) );
  259.  
  260.     if (status == SUCCESS && !foundClient) {
  261.     /*
  262.      * The stream is newly created on this host so we call down to
  263.      * the I/O handle level to ensure that the I/O handle exists and
  264.      * so the local object manager gets told about the new stream.
  265.      */
  266.     migInfoPtr->flags = streamPtr->flags;
  267.     status = (*fsio_StreamOpTable[migInfoPtr->ioFileID.type].migEnd)
  268.         (migInfoPtr, size, data, &streamPtr->ioHandlePtr);
  269.     DEBUG( ("migEnd status %x\n", status) );
  270.     } else {
  271.     DEBUG( ("migrate status %x\n", status) );
  272.     }
  273.     if (streamPtr->offset != savedOffset) {
  274.     DEBUG(("Fsio_DeencapStream \"%s\" srcClientOffset %d ioSrvrOffset %d\n",
  275.         Fsutil_HandleName(streamPtr->ioHandlePtr),
  276.         savedOffset, streamPtr->offset) );
  277.     }
  278.  
  279.     if (status == SUCCESS) {
  280.     assert(streamPtr != (Fs_Stream *)NIL);
  281.     *streamPtrPtr = streamPtr;
  282.     } else {
  283.     Fsutil_HandleLock(streamPtr);
  284.     if (!foundStream &&
  285.         Fsio_StreamClientClose(&streamPtr->clientList, rpc_SpriteID)) {
  286.         Fsio_StreamDestroy(streamPtr);
  287.     } else {
  288.         Fsutil_HandleRelease(streamPtr, TRUE);
  289.     }
  290.     }
  291.  
  292.     return(status);
  293. }
  294.  
  295. /*
  296.  * ----------------------------------------------------------------------------
  297.  *
  298.  * Fsio_MigrateUseCounts --
  299.  *
  300.  *    This updates use counts to reflect any network sharing that
  301.  *    is a result of migration.  The rule adhered to is that there
  302.  *    are use counts kept on the I/O handle for each stream on each client
  303.  *    that uses the I/O handle.  A stream with only one reference
  304.  *    does not change use counts when it migrates, for example, because
  305.  *    the reference just moves.  A stream with two references will
  306.  *    cause a new client host to have a stream after migration, so the
  307.  *    use counts are updated in case both clients do closes.  Finally,
  308.  *    use counts get decremented when a stream completely leaves a
  309.  *    client after being shared.
  310.  *
  311.  * Results:
  312.  *    None.
  313.  *
  314.  * Side effects:
  315.  *    Adjusts the use counts to reflect sharing of the I/O handle
  316.  *    due to migration.
  317.  *
  318.  * ----------------------------------------------------------------------------
  319.  *
  320.  */
  321. void
  322. Fsio_MigrateUseCounts(flags, closeSrcClient, usePtr)
  323.     register int     flags;        /* Flags from the stream */
  324.     Boolean        closeSrcClient;    /* TRUE if I/O close was done at src */
  325.     register Fsio_UseCounts *usePtr;    /* Use counts from the I/O handle */
  326. {
  327.     if ((flags & FS_NEW_STREAM) && !closeSrcClient) {
  328.     /*
  329.      * The stream is becoming shared across the network because
  330.      * it is new at the destination and wasn't closed at the source.
  331.      * Increment the use counts on the I/O handle
  332.      * to reflect the additional client stream.
  333.      */
  334.     usePtr->ref++;
  335.     if (flags & FS_WRITE) {
  336.         usePtr->write++;
  337.     }
  338.     if (flags & FS_EXECUTE) {
  339.         usePtr->exec++;
  340.     }
  341.     } else if ((flags & FS_NEW_STREAM) == 0 && closeSrcClient) {
  342.     /*
  343.      * The stream is becoming un-shared.  The last reference from the
  344.      * source was closed and there is already a reference at the dest.
  345.      * Decrement the use counts to reflect the fact that the stream on
  346.      * the original client is not referencing the I/O handle.
  347.      */
  348.     usePtr->ref--;
  349.     if (flags & FS_WRITE) {
  350.         usePtr->write--;
  351.     }
  352.     if (flags & FS_EXECUTE) {
  353.         usePtr->exec--;
  354.     }
  355.     } else {
  356.     /*
  357.      * The stream moved completely, or a reference just moved between
  358.      * two existing streams, so there is no change visible to
  359.      * the I/O handle use counts.
  360.      */
  361.      }
  362. }
  363.  
  364. /*
  365.  * ----------------------------------------------------------------------------
  366.  *
  367.  * Fsio_MigrateClient --
  368.  *
  369.  *    Move a client of an I/O handle from one host to another.  Flags
  370.  *    indicate if the migration results in a newly shared stream, or
  371.  *    in a stream that is no longer shared, or in a stream with
  372.  *    no change visible at the I/O handle level.  We are careful to only
  373.  *    open the dstClient if it getting the stream for the first time.
  374.  *    Also, if the srcClient is switching from a writer to a reader, we
  375.  *    remove its write reference.
  376.  *
  377.  * Results:
  378.  *    None.
  379.  *
  380.  * Side effects:
  381.  *    Adds the destination client to the clientList, if needed.
  382.  *    Removes the source client from the list, if needed.
  383.  *
  384.  * ----------------------------------------------------------------------------
  385.  */
  386.  
  387. ENTRY void
  388. Fsio_MigrateClient(clientList, srcClientID, dstClientID, flags, closeSrcClient)
  389.     List_Links    *clientList;    /* List of clients for the I/O handle. */
  390.     int        srcClientID;    /* The original client. */
  391.     int        dstClientID;    /* The destination client. */
  392.     int        flags;        /* FS_RMT_SHARED if a copy of the stream
  393.                  * still exists on the srcClient.
  394.                  * FS_NEW_STREAM if stream is new on dst.
  395.                  * FS_READ | FS_WRITE | FS_EXECUTE */
  396.     Boolean    closeSrcClient;    /* TRUE if we should close src client.  This
  397.                  * is set by Fsio_StreamMigClient */
  398. {
  399.     register Boolean found;
  400.     Boolean cache = FALSE;
  401.  
  402.     if (closeSrcClient) {
  403.     /*
  404.      * The stream is not shared so we nuke the original client's use.
  405.      */
  406.     found = Fsconsist_IOClientClose(clientList, srcClientID, flags, &cache);
  407.     if (!found) {
  408.         printf("Fsio_MigrateClient, srcClient %d not found\n", srcClientID);
  409.     }
  410.     }
  411.     if (flags & FS_NEW_STREAM) {
  412.     /*
  413.      * The stream is new on the destination host.
  414.      */
  415.     (void)Fsconsist_IOClientOpen(clientList, dstClientID, flags, FALSE);
  416.     }
  417. }
  418.  
  419.